for in

const obj = {
  id: 1,
  name: "yiliang",
  age: 18,
};

for (let key in obj) {
  console.log(key + "---" + obj[key]);
}
  • 它可与breakcontinuereturn配合使用

for in 的缺陷

给内置原型 Object.prototype 添加属性/方法,for in 时也是可遍历的。如果重写了内置属性, 例如 toString 之类的函数,大多数现代浏览器都是会打印出来的。但是 for in 不会读取不可枚举属性,如数组的 length 属性。

所以不能依赖于 for in 来获取对象的成员名称,一般会配合 hasOwnProperty 打印对象的键值,没人可以保证运行的代码环境是否被污染过。

for-in 遍历数组的问题?

  • for-in赋给 index 的值不是实际的数字,而是字符串 “0”、“1”、“2”,此时很可能在无意之间进行字符串算数计算,例如:“2” + 1 == “21”,这给编码过程带来极大的不便。
  • 作用于数组的 for-in 循环体除了遍历数组元素外,还会遍历自定义属性。举个例子,如果你的数组中有一个可枚举属性 myArray.name,循环将额外执行一次,遍历到名为“name”的索引。就连数组原型链上的属性都能被访问到。

in 操作符

in操作符只要通过对象能访问到属性就返回truein 缺陷---属性是继承来的时候,仍然返回 true. 使用delete操作符则可以完全删除实例属性,但不能删除原型链中的属性。

for of

遍历数组:for-in获取索引for-of获取

for of, for in 和 forEach, map 的区别

  • for in 是遍历对象的。使用 for in 会遍历数组所有的可枚举属性,包括原型。所以for-in 用于遍历对象更好,for in 遍历的是数组的索引(即键名)。for in 用于遍历对象更好
  • for of 用于遍历数组更好,只遍历数组的元素值,不遍历数组对象上挂载的属性。
  • for of 循环:具有 iterator 接口,就可以用 for of 循环遍历它的成员(属性值)。for of 循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象、Generator 对象,以及字符串。for of 循环调用遍历器接口,数组的遍历器接口只返回具有数字索引的属性。对于普通的对象,for of 结构不能直接使用,会报错,必须部署了 Iterator 接口后才能使用。可以中断循环。
  • for in 循环:遍历对象自身的和继承的可枚举的属性, 不能直接获取属性值。可以中断循环。
  • forEach: 只能遍历数组,不能中断,没有返回值(或认为返回值是 undefined)。注意: forEach() 对于空数组是不会执行回调函数的
  • map: 只能遍历数组,不能中断,返回值是修改后的数组

停止 for 循环

break 可以停止 for in 和 for of 循环, 不能停止 forEach 循环。

foreach 跳出循环

try {
  arr.forEach((item, index) => {
    if (item === "b") throw new Error("exist");
    console.log(item);
  });
} catch (e) {
  if (e.message == "exist") throw e;
} finally {
  console.log("done");
}

程序最后可以终止退出循环,所以使用 try...catch 通过抛出异常的方式来终止程序继续执行是可行。

foreach 不能异步原因

foreach 源码:

// ...

Array.prototype.forEach = function (callback, thisArg) {
  var len = O.length >>> 0;
  k = 0;
  // 7. Repeat, while k < len
  while (k < len) {
    if (k in O) {
      // ...
      callback.call(T, kValue, k, O);
    }
    k++;
  }
};
// ...

可以看到代码中有一个 while 循环一直在调用 callback 回调函数,判断这里应该是异步并行调用的,因为我们只是在将 foreach 中的 callback 使用了 async/await 来等待异步返回操作,而本身这个 foreach 并没有使用 async/await 来等待异步返回。

使用 foreach 时其实也就相当于调用了一个封装了 while 或者 for 循环的函数,这个函数本身并没有使用 async/await 来处理异步,所以使用时在回调函数里面加上 async/await 是没有作用的,遍历的方式有很多种,那么我们在需要遍历处理异步的时候,最好还是使用 for 或者 while 来实现,不管是封装一个新的函数,或者是直接使用来遍历都可以避免这个问题。

说一下 for...in 和 for...of 的区别?

for...of 遍历获取的是对象的键值, for...in 获取的是对象的键名; for...in 会遍历对象的整个原型链, 性能非常差不推荐使用,而 for...of 只遍历当前对象不会遍历原型链; 对于数组的遍历,for...in 会返回数组中所有可枚举的属性(包括原型链上可枚举的属性),for...of 只返回数组的下标对应的属性值; 总结:for...in 循环主要是为了遍历对象而生,不适用遍历数组; for....of 循环可以用来遍历数组、类数组对象、字符串、Set、Map 以及 Generator 对象

for each/of/in 之类的区别,map, some, find 之类的区别和使用

Last Updated:
Contributors: yiliang114